
#include "Thread.h"

C_Thread_Ptr
C_Thread_New(C_Thread_Run_t f)
{
	C_Thread_Ptr p = C_Malloc(sizeof(C_Thread));
	C_Thread_Init(p, f);
	return p;
}

void
C_Thread_Init(C_Thread_Ptr p, C_Thread_Run_t f)
{
	if (p == NULL)
		return;
	p->Flags = 0;
	p->Run = C_False;
	p->Function = f;
	p->User = NULL;
	p->Cleanup = C_Thread_Base_Cleanup;
}

void
C_Thread_Base_Cleanup(C_Thread_Ptr p)
{
	///...
}

void
C_Thread_Cleanup(C_Thread_Ptr p)
{
	if (p == NULL)
		return;

	if(p->Cleanup != NULL)
		p->Cleanup(p);
}

void
C_Thread_Free(C_Thread_Ptr p)
{
	if (p == NULL)
		return;
	C_Thread_Cleanup(p);
	C_Free(p);
}

C_Error_t
C_Thread_Run(C_Thread_Ptr p, C_Bool_t detach, void *arg)
{
	C_Thread_Args args;
	int err;

	if (p == NULL || p->Function == NULL)
		return C_ERR_INVALID_PARAMS;

	if (p->Flags & C_THREAD_FLAG_STARTED)
	{
		return C_ERR_INVALID_STATE;
	}

	args.Thread = p;
	args.Args = arg;

	p->Run = C_True;

	//err = pthread_create(&p->Handle, NULL, (void* (*)(void*))f, &args);
	err = pthread_create(&p->Handle, NULL, (void* (*)(void*))p->Function, p);

	if (err != 0)
		return C_ERR_INTERNAL_ERR;

	p->Flags |= C_THREAD_FLAG_STARTED;

	if (detach)
	{
		pthread_detach(p->Handle);
		p->Flags |= C_THREAD_FLAG_DETACHED;
	}

	return C_ERR_NOERR;
}

void
C_Thread_Set_Cleanup(C_Thread_Ptr p, C_Thread_Cleanup_t f)
{
	if (p != NULL)
	{
		p->Cleanup = f;
	}

}

C_Error_t
C_Thread_Stop(C_Thread_Ptr p)
{
	if (p == NULL)
		return C_ERR_INVALID_PARAMS;

	if (!(p->Flags & C_THREAD_FLAG_STARTED))
		return C_ERR_INVALID_STATE;

	p->Run = C_False;

	if (!(p->Flags & C_THREAD_FLAG_DETACHED))
	{
		pthread_join(p->Handle, NULL);
	}

	p->Flags &= (C_THREAD_FLAG_STARTED);

	return C_ERR_NOERR;
}
